// pages/receiver/receiver.js
const dataProcessor = require('../../utils/dataProcessor.js');

Page({
  data: {
    sdkVersion: '',
    statusText: '准备就绪，请点击开始扫描',
    progress: 0,
    currentIndex: 0,
    totalFragments: 0,
    isComplete: false,
    isScanning: false,
    dataType: '',
    resultData: '',
    fileData: null,
    fileName: '',
    isImage: false,
    scanLock: false,
    failedCount: 0,
    lastScannedIndex: -1,
    consecutiveSameCount: 0,
    fragmentsStatus: [],
    canContinue: false
  },

  storedData: null,
  scannedIndexes: new Set(),

  onLoad() {
    const sdkVersion = wx.getSystemInfoSync().SDKVersion;
    this.setData({ sdkVersion });
  },

  /**
   * 开始扫描（清空历史数据）
   */
  startScan() {
    this.scannedIndexes.clear();
    this.storedData = null;
    this.setData({
      isScanning: true,
      statusText: '扫描即将开始...',
      progress: 0,
      currentIndex: 0,
      totalFragments: 0,
      isComplete: false,
      resultData: '',
      fileData: null,
      fileName: '',
      isImage: false,
      failedCount: 0,
      lastScannedIndex: -1,
      consecutiveSameCount: 0,
      fragmentsStatus: [],
      canContinue: false
    });
    this.doScan();
  },

  /**
   * 继续扫描（保留历史数据）
   */
  continueScan() {
    this.setData({
      isScanning: true,
      statusText: '继续扫描中...请对准二维码',
      failedCount: 0,
      consecutiveSameCount: 0,
      scanLock: false
    });
    this.doScan();
  },

  /**
   * 单次扫码逻辑
   */
  doScan() {
    if (!this.data.isScanning || this.data.scanLock) return;
    this.setData({ scanLock: true });

    wx.scanCode({
      onlyFromCamera: true,
      scanType: ['qrCode'],
      success: (res) => {
        this.setData({ scanLock: false });
        this.handleScanResult(res.result, true);
      },
      fail: (err) => {
        this.setData({ scanLock: false });
        this.handleScanResult(null, false);
      }
    });
  },

  /**
   * 处理扫描结果（含自动停止逻辑）
   */
  handleScanResult(fragmentData, isSuccess) {
    // 连续失败处理
    if (!isSuccess) {
      const newFailedCount = this.data.failedCount + 1;
      this.setData({ failedCount: newFailedCount });

      if (newFailedCount >= 3) {
        this.stopScan('连续3次扫描失败，已停止', true);
        return;
      }
    } else {
      this.setData({ failedCount: 0 });
    }

    // 解析失败处理
    let fragment;
    try {
      fragment = dataProcessor.parseFragment(fragmentData);
    } catch (err) {
      this.handleScanResult(null, false);
      return;
    }

    // 连续重复扫描处理
    if (fragment.index === this.data.lastScannedIndex) {
      const newSameCount = this.data.consecutiveSameCount + 1;
      this.setData({
        consecutiveSameCount: newSameCount,
        lastScannedIndex: fragment.index
      });

      if (newSameCount >= 3) {
        this.stopScan('连续扫描到相同分片，已停止', true);
        return;
      }
    } else {
      this.setData({
        consecutiveSameCount: 0,
        lastScannedIndex: fragment.index
      });
    }

    // 处理分片并继续扫描
    this.processFragment(fragment);
    if (!this.data.isComplete && this.data.isScanning) {
      setTimeout(() => this.doScan(), 500);
    }
  },

  /**
   * 处理分片数据
   */
  processFragment(fragment) {
    // 初始化分片状态列表
    if (this.data.totalFragments === 0) {
      const statusList = Array.from({ length: fragment.total }, (_, i) => ({
        index: i + 1,
        received: false
      }));
      this.setData({
        totalFragments: fragment.total,
        fragmentsStatus: statusList
      });
    }

    // 去重处理
    if (this.scannedIndexes.has(fragment.index)) {
      return;
    }
    this.scannedIndexes.add(fragment.index);

    // 更新分片状态
    const updatedStatus = this.data.fragmentsStatus.map(item => 
      item.index === fragment.index ? { ...item, received: true } : item
    );
    this.setData({ fragmentsStatus: updatedStatus });

    // 记录文件名（文件类型时，使用过滤后的名称）
    if (fragment.type === 'file' && fragment.fileName) {
      const pureFileName = this.extractPureFileName(fragment.fileName);
      this.setData({ fileName: pureFileName });
    }

    // 单分片文本处理
    if (fragment.total === 1 && fragment.type === 'str') {
      this.completeTransfer({
        total: 1,
        type: 'str',
        fragments: { 1: fragment.data }
      });
      this.stopScan('', false);
      return;
    }

    // 多分片累计
    const { storedData, isComplete } = dataProcessor.accumulateFragment(
      fragment,
      this.storedData
    );
    this.storedData = storedData;

    // 更新进度
    const progress = Math.round(
      (Object.keys(storedData.fragments).length / storedData.total) * 100
    );
    this.setData({
      progress,
      currentIndex: fragment.index,
      statusText: `已接收第${fragment.index}/${storedData.total}片`
    });

    // 完成所有分片
    if (isComplete) {
      this.completeTransfer(storedData);
      this.stopScan('', false);
    }
  },

  /**
   * 停止扫描
   */
  stopScan(customText, canContinue = false) {
    const stopText = customText || '已停止扫描';
    this.setData({ 
      isScanning: false,
      statusText: stopText,
      canContinue: canContinue && !this.data.isComplete
    });
  },

  /**
   * 传输完成处理
   */
  completeTransfer(storedData) {
    try {
      const mergedBase64 = dataProcessor.mergeFragments(storedData);
      const buffer = dataProcessor.base64Decode(mergedBase64);

      if (storedData.type === 'str') {
        // 文本UTF-8解码
        const text = this.utf8Decode(buffer);
        this.setData({
          isComplete: true,
          dataType: 'text',
          resultData: text,
          statusText: '文本传输完成'
        });
        wx.showToast({ title: '文本解析成功', icon: 'success' });

        // 保存文本记录
        this.saveRecord({
          type: 'text',
          content: text,
          fileData: null,
          filePath: null,
          fileName: '',
          time: Date.now()
        });
      } else if (storedData.type === 'file') {
        // 强制提取纯文件名（双重保险）
        let fileName = this.data.fileName || 'unknown_file';
        fileName = this.extractPureFileName(fileName);
        
        // 判断是否为图片
        const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'];
        const fileExt = fileName.split('.').pop().toLowerCase();
        const isImage = imageExts.includes(fileExt);

        // 保存文件到临时路径
        const filePath = `${wx.env.USER_DATA_PATH}/${fileName}`;
        wx.getFileSystemManager().writeFile({
          filePath,
          data: buffer,
          encoding: 'binary',
          success: () => {
            this.setData({
              isComplete: true,
              dataType: 'file',
              fileData: buffer,
              fileName: fileName,
              isImage: isImage,
              statusText: `文件传输完成（${fileName}）`
            });
            wx.showToast({ title: `文件解析成功（${fileName}）`, icon: 'success' });

            // 保存文件记录
            this.saveRecord({
              type: 'file',
              content: '',
              fileData: buffer.toString('base64'),
              filePath: filePath,
              fileName: fileName,
              time: Date.now()
            });
          },
          fail: (err) => {
            console.error('文件保存失败:', err);
            wx.showToast({ title: '文件保存失败', icon: 'none' });
          }
        });
      }

    } catch (err) {
      console.error('[解析失败]', err.message);
      wx.showToast({ title: '解析失败', icon: 'none' });
    }
  },

  /**
   * 保存接收记录
   */
  saveRecord(record) {
    const records = wx.getStorageSync('dataRecords') || [];
    records.unshift(record);
    wx.setStorageSync('dataRecords', records);
  },

  /**
   * UTF-8解码
   */
  utf8Decode(buffer) {
    const uint8Array = new Uint8Array(buffer);
    let text = '';
    let i = 0;
    while (i < uint8Array.length) {
      const byte1 = uint8Array[i];
      if (byte1 < 0x80) {
        text += String.fromCharCode(byte1);
        i++;
      } else if (byte1 >= 0xE0 && byte1 <= 0xEF && i + 2 < uint8Array.length) {
        const byte2 = uint8Array[i + 1];
        const byte3 = uint8Array[i + 2];
        const code = ((byte1 & 0x0F) << 12) | ((byte2 & 0x3F) << 6) | (byte3 & 0x3F);
        text += String.fromCharCode(code);
        i += 3;
      } else if (byte1 >= 0xC0 && byte1 <= 0xDF && i + 1 < uint8Array.length) {
        const byte2 = uint8Array[i + 1];
        const code = ((byte1 & 0x1F) << 6) | (byte2 & 0x3F);
        text += String.fromCharCode(code);
        i += 2;
      } else {
        i++;
      }
    }
    return text;
  },

  /**
   * 复制文本
   */
  copyText() {
    const text = this.data.resultData;
    if (!text) {
      wx.showToast({ title: '无文本可复制', icon: 'none' });
      return;
    }
    wx.setClipboardData({
      data: text,
      success() { wx.showToast({ title: '已复制到剪贴板', icon: 'success' }); },
      fail() { wx.showToast({ title: '复制失败', icon: 'none' }); }
    });
  },

  /**
   * 图片保存到相册
   */
  saveImageToAlbum() {
    if (!this.data.isImage || !this.data.fileData || !this.data.fileName) {
      wx.showToast({ title: '不支持的文件类型', icon: 'none' });
      return;
    }

    // 检查相册权限
    this.checkAlbumPermission().then(() => {
      const fs = wx.getFileSystemManager();
      const pureFileName = this.extractPureFileName(this.data.fileName);
      const tempPath = `${wx.env.USER_DATA_PATH}/${pureFileName}`;

      // 写入临时文件
      fs.writeFile({
        filePath: tempPath,
        data: this.data.fileData,
        encoding: 'binary',
        success: () => {
          wx.saveImageToPhotosAlbum({
            filePath: tempPath,
            success: () => {
              wx.showModal({
                title: '保存成功',
                content: `图片已保存到手机相册\n文件名：${pureFileName}`,
                showCancel: false
              });
            },
            fail: (err) => {
              console.error('相册保存失败', err);
              wx.showToast({ title: '保存失败，请重试', icon: 'none' });
            }
          });
        },
        fail: (err) => {
          console.error('临时图片写入失败', err);
          wx.showToast({ title: '保存失败，请重试', icon: 'none' });
        }
      });
    }).catch(() => {
      wx.showModal({
        title: '需要相册权限',
        content: '请允许访问相册以保存图片',
        confirmText: '去设置',
        success: (res) => res.confirm && wx.openSetting()
      });
    });
  },

  /**
   * 提取文件后缀并映射为微信支持的类型（将.cmake视为txt）
   */
  getFileExt(fileName) {
    const ext = fileName.split('.').pop().toLowerCase();
    // 扩展支持列表：将cmake映射为txt（因为都是文本文件）
    const typeMap = {
      'cmake': 'txt',    // 关键：.cmake文件按文本处理
      'doc': 'doc',
      'docx': 'docx',
      'xls': 'xls',
      'xlsx': 'xlsx',
      'ppt': 'ppt',
      'pptx': 'pptx',
      'pdf': 'pdf',
      'txt': 'txt',
      'json': 'json',
      'xml': 'xml'
    };
    // 若不在映射表中，默认尝试按txt打开（文本文件通用）
    return typeMap[ext] || 'txt';
  },

  /**
   * 文档文件：打开后让用户手动保存（替代wx.saveFile）
   */
  openAndSaveDoc() {
    if (this.data.isImage || !this.data.fileData || !this.data.fileName) {
        wx.showToast({ title: '文件信息不完整', icon: 'none' });
        return;
      }
    
      wx.showLoading({ title: '准备文件...' });
      const fs = wx.getFileSystemManager();
      const pureFileName = this.extractPureFileName(this.data.fileName);
      const tempPath = `${wx.env.USER_DATA_PATH}/${pureFileName}`;

      console.log(tempPath);
      //fs.unlinkSync(tempPath);
      try {
        // 步骤1：写入临时文件
        fs.writeFileSync(tempPath, this.data.fileData, 'binary');
        
        // 步骤2：验证文件是否存在且非空
        const stat = fs.statSync(tempPath);
        if (stat.size === 0) {
          throw new Error('文件内容为空');
        }
        
        // 步骤3：尝试读取文件内容（验证完整性）
        const content = fs.readFileSync(tempPath, 'utf8'); // 文本文件用utf8读取
        console.log('文件内容预览:', content.substring(0, 100)); // 打印前100字符确认
        
        // // 步骤4：打开文件（强制按txt类型）
        wx.hideLoading();
        wx.openDocument({
          filePath: tempPath,
          showMenu: true,
          fileType: 'doc', // 强制指定为文本类型，忽略扩展名
          success: () => {
            console.log('文件打开成功');
          },
          fail: (err) => {
            console.error('打开文件失败:', err);
            this.handleOpenFail(tempPath, pureFileName, content);
          }
        });
      } catch (err) {
        wx.hideLoading();
        console.error('文件处理失败:', err);
        wx.showModal({
          title: '文件准备失败',
          content: `原因：${err.message}\n可尝试重新传输文件`,
          showCancel: false
        });
      }
  },

  /**
   * 打开失败时的备选方案：显示文本内容供用户复制
   */
  handleOpenFail(tempPath, fileName, content) {
    wx.showModal({
      title: '无法打开文件',
      content: `文件可能损坏或不支持直接打开。\n是否查看文本内容并手动复制？`,
      confirmText: '查看内容',
      cancelText: '取消',
      success: (res) => {
        if (res.confirm) {
          // 跳转到文本查看页（需创建一个新页面）
          wx.navigateTo({
            url: `/pages/textView/textView?content=${encodeURIComponent(content)}&fileName=${fileName}`
          });
        }
      }
    });
  },

  /**
   * 提取纯文件名（剥离路径+过滤特殊字符）
   */
  extractPureFileName(rawName) {
    if (!rawName) return 'unknown_file';
    
    // 步骤1：剥离路径（处理/、\、:等路径分隔符）
    const separators = ['/', '\\', ':'];
    let pureName = rawName;
    separators.forEach(sep => {
      const lastIndex = pureName.lastIndexOf(sep);
      if (lastIndex !== -1) {
        pureName = pureName.substring(lastIndex + 1);
      }
    });
    
    // 步骤2：过滤特殊字符（保留字母、数字、. _ -）
    pureName = pureName.replace(/[^a-zA-Z0-9._-]/g, '_').replace(/_+/g, '_');
    
    // 步骤3：处理空文件名
    return pureName.trim() || 'unknown_file';
  },

  /**
   * 检查相册权限
   */
  checkAlbumPermission() {
    return new Promise((resolve, reject) => {
      wx.getSetting({
        success: (res) => {
          if (res.authSetting['scope.writePhotosAlbum']) {
            resolve();
          } else {
            wx.authorize({ scope: 'scope.writePhotosAlbum', success: resolve, fail: reject });
          }
        },
        fail: reject
      });
    });
  },

  /**
   * 重置任务
   */
  resetTask() {
    this.stopScan();
    this.storedData = null;
    this.scannedIndexes.clear();
    this.setData({
      statusText: '准备就绪，请点击开始扫描',
      progress: 0,
      currentIndex: 0,
      totalFragments: 0,
      isComplete: false,
      dataType: '',
      resultData: '',
      fileData: null,
      fileName: '',
      isImage: false,
      fragmentsStatus: [],
      canContinue: false
    });
  },

  onUnload() {
    this.stopScan();
  }
});